import os
import logging
from typing import Optional
from urllib.parse import urljoin
from app.core.config import settings

logger = logging.getLogger(__name__)


class StorageService:
    """对象存储服务 - 通用适配器"""
    
    def __init__(self):
        self.provider = settings.STORAGE_PROVIDER
        self.bucket_name = settings.S3_BUCKET
        self.client = None
        self._init_client()
    
    def _init_client(self):
        """初始化存储客户端"""
        try:
            import boto3
            from botocore.client import Config
            from botocore.exceptions import NoCredentialsError
            
            # 配置S3兼容客户端
            self.client = boto3.client(
                's3',
                endpoint_url=settings.S3_ENDPOINT,
                aws_access_key_id=settings.S3_ACCESS_KEY,
                aws_secret_access_key=settings.S3_SECRET_KEY,
                region_name=settings.S3_REGION,
                config=Config(
                    signature_version='s3v4',
                    s3={
                        'addressing_style': 'path'  # 使用路径风格访问
                    }
                )
            )
            
            # 检查并创建bucket
            self._ensure_bucket_exists()
            logger.info(f"Storage service initialized with provider: {self.provider}")
            
        except Exception as e:
            logger.error(f"Failed to initialize storage client: {e}")
            self.client = None
    
    def _ensure_bucket_exists(self):
        """确保bucket存在"""
        if not self.client:
            return
            
        try:
            # 检查bucket是否存在
            self.client.head_bucket(Bucket=self.bucket_name)
            logger.info(f"Bucket '{self.bucket_name}' already exists")
        except Exception:
            try:
                # 创建bucket
                self.client.create_bucket(Bucket=self.bucket_name)
                logger.info(f"Created bucket '{self.bucket_name}'")
            except Exception as e:
                logger.error(f"Failed to create bucket '{self.bucket_name}': {e}")
    
    def upload_file(self, file_path: str, object_name: str, content_type: Optional[str] = None) -> Optional[str]:
        """上传文件并返回访问URL"""
        if not self.client:
            logger.error("Storage client not initialized")
            return None
        
        if not os.path.exists(file_path):
            logger.error(f"File not found: {file_path}")
            return None
        
        try:
            # 准备上传参数
            extra_args = {}
            if content_type:
                extra_args['ContentType'] = content_type
            else:
                # 根据文件扩展名推断content type
                ext = os.path.splitext(file_path)[1].lower()
                content_type_map = {
                    '.jpg': 'image/jpeg',
                    '.jpeg': 'image/jpeg',
                    '.png': 'image/png',
                    '.gif': 'image/gif',
                    '.webp': 'image/webp',
                    '.svg': 'image/svg+xml'
                }
                if ext in content_type_map:
                    extra_args['ContentType'] = content_type_map[ext]
            
            # 上传文件
            self.client.upload_file(
                file_path, 
                self.bucket_name, 
                object_name,
                ExtraArgs=extra_args
            )
            
            # 生成访问URL
            if settings.S3_ENDPOINT:
                # 对于MinIO等自建服务
                url = f"{settings.S3_ENDPOINT.rstrip('/')}/{self.bucket_name}/{object_name}"
            else:
                # 对于AWS S3
                url = f"https://{self.bucket_name}.s3.{settings.S3_REGION}.amazonaws.com/{object_name}"
            
            logger.info(f"File uploaded successfully: {object_name}")
            return url
            
        except Exception as e:
            logger.error(f"Failed to upload file {file_path}: {e}")
            return None
    
    def download_file(self, object_name: str, destination_path: str) -> bool:
        """下载文件"""
        if not self.client:
            logger.error("Storage client not initialized")
            return False
        
        try:
            # 确保目标目录存在
            os.makedirs(os.path.dirname(destination_path), exist_ok=True)
            
            # 下载文件
            self.client.download_file(self.bucket_name, object_name, destination_path)
            logger.info(f"File downloaded successfully: {object_name} -> {destination_path}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to download file {object_name}: {e}")
            return False
    
    def delete_file(self, object_name: str) -> bool:
        """删除文件"""
        if not self.client:
            logger.error("Storage client not initialized")
            return False
        
        try:
            self.client.delete_object(Bucket=self.bucket_name, Key=object_name)
            logger.info(f"File deleted successfully: {object_name}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to delete file {object_name}: {e}")
            return False
    
    def get_file_url(self, object_name: str, expires_in: int = 3600) -> Optional[str]:
        """生成文件的预签名URL"""
        if not self.client:
            logger.error("Storage client not initialized")
            return None
        
        try:
            url = self.client.generate_presigned_url(
                'get_object',
                Params={'Bucket': self.bucket_name, 'Key': object_name},
                ExpiresIn=expires_in
            )
            return url
            
        except Exception as e:
            logger.error(f"Failed to generate presigned URL for {object_name}: {e}")
            return None
    
    def list_files(self, prefix: str = "") -> list:
        """列出文件"""
        if not self.client:
            logger.error("Storage client not initialized")
            return []
        
        try:
            response = self.client.list_objects_v2(
                Bucket=self.bucket_name,
                Prefix=prefix
            )
            
            files = []
            if 'Contents' in response:
                for obj in response['Contents']:
                    files.append({
                        'key': obj['Key'],
                        'size': obj['Size'],
                        'last_modified': obj['LastModified']
                    })
            
            return files
            
        except Exception as e:
            logger.error(f"Failed to list files with prefix {prefix}: {e}")
            return []
    
    def is_available(self) -> bool:
        """检查存储服务是否可用"""
        return self.client is not None


# 创建全局实例
storage_service = StorageService()